/* ****************************************************************************
 *
 * Copyright (c) Microsoft Corporation. 
 *
 * This source code is subject to terms and conditions of the Microsoft Public License. A 
 * copy of the license can be found in the License.html file at the root of this distribution. If 
 * you cannot locate the  Microsoft Public License, please send an email to 
 * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound 
 * by the terms of the Microsoft Public License.
 *
 * You must not remove this notice, or any other, from this software.
 *
 * THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
 * KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
 * PARTICULAR PURPOSE.
 * ***************************************************************************/



#if !defined(AFX_PGLAXE2D_H__4DACBB7A_9EFC_11D4_8A95_D4B14EEC3D7F__INCLUDED_)
#define AFX_PGLAXE2D_H__4DACBB7A_9EFC_11D4_8A95_D4B14EEC3D7F__INCLUDED_

#include <pgl/core/PGLObject.h>
#include <pgl/core/PGLLine.h>
#include <pgl/core/PGLText.h>
#include <pgl/core/PGLView2D.h>
#include <pgl/core/PGLArchive.h>
#include <pgl/core/PGLNumbering.h>


#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

/*! \brief Axis handling numbering, label positioning, time labelling, etc...
\ingroup PGLTextGroup


\todo logarithmic scales.
*/
class PGLCORE_EXT_CLASS CPGLAxe2D  : public CPGLObject
{
PGL_DECLARE_DYNCREATE(CPGLAxe2D);
public:

	//! \name Constructors
	//@{
	//! default constructor
	CPGLAxe2D(CPGLView2D* pView=NULL);
	//! copy constructor
	CPGLAxe2D(const CPGLAxe2D& a){*this=a;};
	//! assignement constructor
	CPGLAxe2D& operator=(const CPGLAxe2D& a) ;
	//! destructor
	virtual ~CPGLAxe2D();
	//! Destroy axe
	//@}

	//! \name Region View
	//@{
	//! Sets the pointer to the parent CPGLRegion view
	void SetView(CPGLView2D* pView)		{	ASSERT_VALID(pView); m_pView=pView; };
	//! return a pointer to the parent CPGLRegion view
	CPGLView2D* GetView()				{	return m_pView;};
	//@}

	//! \name Limits
	//@{
	/*! Sets limits, OBSOLETE function
	\todo do not use this function anymore
	*/
	void SetLimits(int iaxe, double _start,double _end,gfxinterface::CGfxInterface& gfx);
	//! Sets limits
	void SetLimits(const CPGLRectD& rLimits,gfxinterface::CGfxInterface& gfx);
	//! returns limits
	void GetLimits(CPGLRectD& rLimits);
	//! Grows the extents in pExt to show axe.
	void GrowExtent(CPGLRectD& rExtent, const CPGLRectD* pOutsideBorders = NULL , const CPGLRectD* pInsideBorders = NULL);
	/*! return square axis bit
	When using square axis options, horizontal extent and vertical extent have the same value.
	Default value is disabled.
	*/
	bool IsSquare() const				 { return m_bAxisSquare;};
	//! return square axis bit
	void SetSquare(bool squareOn = true ){	m_bAxisSquare = squareOn;};
	//@}

	//! \name Labels
	//@{
	/*! ELabelIndex
	Label indexing, 
	\sa IsShowLabel, SetShowLabel
	*/
	enum ELabelIndex {	
		//! bottom label index
		ELabelBottom=0, 
		//! left label index
		ELabelLeft=1, 
		//! right label index
		ELabelRight=2, 
		//! top label index
		ELabelTop=3
	};

	//! return true if label i ( bottom, left, right, top) is visible
	bool IsShowLabel(ELabelIndex eLabel) const {	return m_pLabels[eLabel].IsVisible();};
	//! return label i visibility( bottom, left, right, top)
	void SetShowLabel(ELabelIndex eLabel,bool on=TRUE) {	m_pLabels[eLabel].Show(on);};

	//! returns a pointer the iLabel label object
	CPGLText& GetLabel(ELabelIndex eLabel)			{	return m_pLabels[eLabel];};
	//! returns a pointer the bottom label object
	CPGLText& GetBottomLabel()						{	return m_pLabels[ELabelBottom];}	
	//! returns a pointer the left label object
	CPGLText& GetLeftLabel()						{	return m_pLabels[ELabelLeft];}	
	//! returns a pointer the right label object
	CPGLText& GetRightLabel()						{	return m_pLabels[ELabelRight];}	
	//! returns a pointer the top label (title) object
	CPGLText& GetTopLabel()							{	return m_pLabels[ELabelTop];}	
	//! returns a pointer the top label (title) object
	CPGLText& GetTitle()							{	return m_pLabels[ELabelTop];}	

	//! Sets the iLabel equal to newLabel
	void SetLabel(ELabelIndex eLabel, const CPGLText& newLabel);
	//! Set the iLabel text equal to newLabel
	void SetLabel(ELabelIndex eLabel, LPCTSTR szNewLabel)			{	m_pLabels[eLabel].SetString(szNewLabel);};

	//! Sets the bottom label equal to newLabel
	void SetBottomLabel(const CPGLText& newLabel)	{ SetLabel(ELabelBottom,newLabel); };
	//! Sets the bottom label text equal to newLabel
	void SetBottomLabel(LPCTSTR newLabel)			{ SetLabel(ELabelBottom,newLabel); };
	//! Sets the left label equal to newLabel
	void SetLeftLabel(const CPGLText& newLabel)		{ SetLabel(ELabelLeft,newLabel); };
	//! Sets the left label text equal to newLabel
	void SetLeftLabel(LPCTSTR newLabel)				{ SetLabel(ELabelLeft,newLabel); };
	//! Sets the right label equal to newLabel
	void SetRightLabel(const CPGLText& newLabel)	{ SetLabel(ELabelRight,newLabel); };
	//! Sets the right label text equal to newLabel
	void SetRightLabel(LPCTSTR newLabel)			{ SetLabel(ELabelRight,newLabel); };
	//! Sets the top label equal to newLabel
	void SetTopLabel(const CPGLText& newLabel)		{ SetLabel(ELabelTop,newLabel); };
	//! Sets the top label text equal to newLabel
	void SetTopLabel(LPCTSTR newLabel)				{ SetLabel(ELabelTop,newLabel); };
	//! Sets the title (top) label equal to newLabel
	void SetTitle(const CPGLText& tTitle)			{ SetLabel(ELabelTop,tTitle); };
	//! Sets the title (top) label text equal to newLabel
	void SetTitle(LPCTSTR tTitle)					{ SetLabel(ELabelTop,tTitle); };
	//! update labels (position,etc...)
	void UpdateLabels(gfxinterface::CGfxInterface& gfx);
	//@}

	//! \name Numbering
	//@{
	//! ELabelIndex
	enum ENumberingIndex {	
		//! bottom number index
		ENumberingBottom=0, 
		//! left number index
		ENumberingLeft=1, 
		//! right number index
		ENumberingRight=2, 
		//! top number index
		ENumberingTop=3};
	//! Shows i-th number
	bool IsShowNumbers(ENumberingIndex eNumber) const	{	return m_pNumbers[eNumber].IsVisible();};
	//! Sets i-th number visibility
	void SetShowNumbers(ENumberingIndex eNumber,bool on=TRUE) {	m_pNumbers[eNumber].Show(on);};

	/*! \brief returns the object controlling the numbering

	\param eNumber enumeration describing the number object
	*/
	CPGLText& GetNumber(ENumberingIndex eNumber)	{	return m_pNumbers[eNumber];};
	//! returns the object controlling the bottom numbering
	CPGLText& GetBottomNumber()						{	return m_pNumbers[ENumberingBottom];}	
	//! returns the object controlling the left numbering
	CPGLText& GetLeftNumber()						{	return m_pNumbers[ENumberingLeft];}	
	//! returns the object controlling the right numbering
	CPGLText& GetRightNumber()						{	return m_pNumbers[ENumberingRight];}	
	//! returns the object controlling the top numbering
	CPGLText& GetTopNumber()						{	return m_pNumbers[ENumberingTop];}	

	/*! \brief Sets the text object controlling the numbering appearance

	\param eNumber enumeration identifying the numbering
	\param textType text appearance of the numbering
	*/
	void SetNumber(ENumberingIndex eNumber, const CPGLText& textType)	{ m_pNumbers[eNumber] = textType;};
	/*! \brief Sets the bottom numbering appearance

	\param textType text appearance of the numbering
	\sa SetNumber
	*/
	void SetBottomNumber(const CPGLText& textType)						{ SetNumber(ENumberingBottom,textType); };
	/*! \brief Sets the left numbering appearance

	\param textType text appearance of the numbering
	\sa SetNumber
	*/
	void SetLeftNumber(const CPGLText& textType)						{ SetNumber(ENumberingLeft,textType); };
	/*! \brief Sets the right numbering appearance

	\param textType text appearance of the numbering
	\sa SetNumber
	*/
	void SetRightNumber(const CPGLText& textType)						{ SetNumber(ENumberingRight,textType); };
	/*! \brief Sets the top numbering appearance

	\param textType text appearance of the numbering
	\sa SetNumber
	*/
	void SetTopNumber(const CPGLText& textType)							{ SetNumber(ENumberingTop,textType); };

	/*! \brief Returns the numbering position

	\param eNumber enumeration identifying the numbering

	The numbering position is the normalized position on the chart: from 0 (left or bottom)  to 1 (right or top)
	*/
	double GetNumberPos(ENumberingIndex eNumber) const					{ return m_pNumberPos[eNumber]; };

	/*! \brief Returns the bottom numbering position

	\sa GetNumberPos
	*/
	double GetBottomNumberPos() const									{	return m_pNumberPos[ENumberingBottom]; };
	/*! \brief Returns the left numbering position

	\sa GetNumberPos
	*/
	double GetLeftNumberPos() const										{	return m_pNumberPos[ENumberingLeft]; };
	/*! \brief Returns the right numbering position

	\sa GetNumberPos
	*/
	double GetRightNumberPos() const									{	return m_pNumberPos[ENumberingRight]; };
	/*! \brief Returns the top numbering position

	\sa GetNumberPos
	*/
	double GetTopNumberPos() const										{	return m_pNumberPos[ENumberingTop]; };

	/*! \brief Sets the numbering position

	\param eNumber enumeration identifying the numbering
	\param pos the numbering position. pos is clipped in [0,1]

	The numbering position is the normalized position on the chart: from 0 (left or bottom)  to 1 (right or top)
	*/
	void SetNumberPos(ENumberingIndex eNumber, double pos)				{	m_pNumberPos[eNumber] = __max(0, __min(1, pos));};
	/*! \brief Sets the bottom numbering position

 	\param pos the numbering position. pos is clipped in [0,1]
	\sa SetNumberPos
	*/
	void SetBottomNumberPos(double pos)									{	SetNumberPos(ENumberingBottom,pos);};
	/*! \brief Sets the left numbering position

 	\param pos the numbering position. pos is clipped in [0,1]
	\sa SetNumberPos
	*/
	void SetLeftNumberPos(double pos)									{	SetNumberPos(ENumberingLeft,pos);};
	/*! \brief Sets the right numbering position

 	\param pos the numbering position. pos is clipped in [0,1]
	\sa SetNumberPos
	*/
	void SetRightNumberPos(double pos)									{	SetNumberPos(ENumberingRight,pos);};
	/*! \brief Sets the top numbering position

 	\param pos the numbering position. pos is clipped in [0,1]
	\sa SetNumberPos
	*/
	void SetTopNumberPos(double pos)									{	SetNumberPos(ENumberingTop,pos);};

	//! Sets the number format string, see printf string format for more info
	void SetNumberFormat(ENumberingIndex iNumber, LPCTSTR szFormat)			{	m_pNumbers[iNumber].SetDescription(szFormat);	};
	//! Returns the number format string, see printf string format for more info
	LPCTSTR GetNumberFormat(ENumberingIndex iNumber) const					{	return m_pNumbers[iNumber].GetDescription();	};
	//! Sets exponent basis for numbering
	void SetNumberExponentLimit(ENumberingIndex iNumber, UINT uExpLimit)	{	m_pNumberExpLimits[iNumber]=uExpLimit;};		
	//! returns the exponent basis for numbering
	UINT GetNumberExponentLimit(ENumberingIndex iNumber)					{	return m_pNumberExpLimits[iNumber];};		
	//! compute exponent scaling
	static int GetExponentScaling( double dStart, double dEnd, double dExpLimit);
	//@}

	//!\name Time labels
	//@{
	//! returns true if time labelling is enabled
	bool IsTimeLabel() const							{	return m_bTimeLabel;};
	//! returns time corresponding to 0
	const COleDateTime& GetTimeLabelOrig() const		{	return m_tTimeLabelOrig;};
	//! returns time elapsed for 1 unit
	const COleDateTimeSpan& GetTimeLabelStep() const	{	return m_tsDt;};
	//! returns the time string format
	const CString& GetTimeLabelString() const			{	return m_sTimeLabel;};
	//! control the time labelling state, default is disabled
	void SetTimeLabel(bool yes = true)					{	m_bTimeLabel=yes;};
	/* \brief sets up the time labelling

	\param _tOrig time corresponding to 0
	\param _tsDt time per unit
	\param _szTimeLabel string format
	*/
	void SetTimeLabelFormat(const CTime& _tOrig, const CTimeSpan& _tsDt, LPCTSTR _szTimeLabel);
	/* \brief sets up the time labelling

	\param _tOrig time corresponding to 0
	\param _tsDt time per unit
	\param _szTimeLabel string format
	*/
	void SetTimeLabelFormat(const COleDateTime& _tOrig, const COleDateTimeSpan& _tsDt, LPCTSTR _szTimeLabel);
	//@}

	//! \name Grid
	//@{
	//! Axis identification
	enum EAxis
	{
		//! horizontal axis
		AxisHorizontal=0,
		//! vertical axis
		AxisVertical=1
	};

	//! returns true if horizontal grid is positive
	bool IsHorGridVisible() const			{	return m_lHorGrid.IsVisible();};
	//! returns true if vertical grid is positive
	bool IsVerGridVisible() const			{	return m_lVerGrid.IsVisible();};
	//! sets the visibility state of the horizontal grid, default is true
	void ShowHorGrid( bool show = true)		{	m_lHorGrid.Show(show);};
	//! sets the visibility state of the vertical grid, default is true
	void ShowVerGrid( bool show = true)		{	m_lVerGrid.Show(show);};
	//! sets the line object controlling the grid appearance of the horizontal grid
	void SetHorGrid(const CPGLLine& l)		{	m_lHorGrid = l;};
	//! sets the line object controlling the grid appearance of the vertical grid
	void SetVerGrid(const CPGLLine& l)		{	m_lVerGrid = l;};
	//! return the line object controlling the grid appearance of the horizontal grid, const
	const CPGLLine& GetHorGrid() const		{	return m_lHorGrid;};
	//! return the line object controlling the grid appearance of the horizontal grid
	CPGLLine& GetHorGrid()					{	return m_lHorGrid;};
	//! return the line object controlling the grid appearance of the vertical grid, const
	const CPGLLine& GetVerGrid() const		{	return m_lVerGrid;};
	//! return the line object controlling the grid appearance of the vertical grid
	CPGLLine& GetVerGrid()					{	return m_lVerGrid;};

	/*! returns true if numbering step is automatic.
	\param i 0 for horizontal, 1 for vertical
	*/
	bool IsAutoSteps(EAxis i) const				{	return m_pAutoSteps[i];};
	//! Sets the auto step mode
	void SetAutoSteps(EAxis i, bool on=true)	{	m_pAutoSteps[i]=on;};
	//! returns the grid step of the corresponding axis
	double GetGridStep(EAxis i) const			{	ASSERT(i>=0 && i<2); return m_pSteps[i];};
	/*! \brief Sets the grid step of the corresponding axis

	\param i enumeration member identifying the axis
	\param step step of the grid
	*/
	void SetGridStep(EAxis i, double step)		{	ASSERT(step > 0); m_pSteps[i]=step;};

	//! Sets the desired number of steps with automitic numbering
	void SetNSteps(int i, UINT nSteps)	{ ASSERT(i==0 || i==1); m_pNSteps[i] = __max(2,nSteps);}
	//! Sets the desired number of steps with automitic numbering
	UINT GetNSteps(int i) const	{ ASSERT(i==0 || i==1); return m_pNSteps[i];}
	//! generate the numbering steps for the axis
	void GenerateSteps(EAxis iaxe);
	//@}

	//! \name Main/Secondary ticks
	//@{
	//! ELabelIndex
	enum ETickIndex {	
		//! bottom number index
		ETickBottom=0, 
		//! left number index
		ETickLeft=1, 
		//! right number index
		ETickRight=2, 
		//! top number index
		ETickTop=3};

	/*!\brief Sets the main tick size
	
	  \param eIndex enumeration identifying the ticks position
	  \param pixels dimension of the tick in pixels (can be negative)
	*/
	void SetMainTicksSize(ETickIndex eIndex, double pixels)				{ m_pMainTicksSize[eIndex] = pixels;};
	/*! \brief sets the bottom main tick size in pixels
	\sa SetMainTicksSize
	*/
	void SetBottomMainTicksSize(double pixels)							{	m_pMainTicksSize[ETickBottom] = pixels;};
	/*! \brief sets the left main tick size in pixels
	\sa SetMainTicksSize
	*/
	void SetLeftMainTicksSize(double pixels)							{	m_pMainTicksSize[ETickLeft] = pixels;};
	/*! \brief sets the right main tick size in pixels
	\sa SetMainTicksSize
	*/
	void SetRightMainTicksSize(double pixels)							{	m_pMainTicksSize[ETickRight] = pixels;};
	/*! \brief sets the top main tick size in pixels
	\sa SetMainTicksSize
	*/
	void SetTopMainTicksSize(double pixels)								{	m_pMainTicksSize[ETickTop] = pixels;};
	/*! \brief sets all main tick size in pixels
	\sa SetMainTicksSize
	*/
	void SetAllMainTicksSize(double pixels)								{	for (UINT i=0;i<4;i++) m_pMainTicksSize[i] = pixels;};

	/*!\brief Returns the main tick size
	
	  \param eIndex enumeration identifying the ticks position
	*/
	double GetMainTicksSize(ETickIndex eIndex) const					{	return m_pMainTicksSize[eIndex]; };
	/*!\brief returns the bottom main tick size in pixels
	
	\sa GetMainTicksSize
	*/
	double GetBottomMainTicksSize()const								{	return m_pMainTicksSize[ETickBottom];};
	/*!\brief returns the left main tick size in pixels
	
	\sa GetMainTicksSize
	*/
	double GetLeftMainTicksSize()const									{	return m_pMainTicksSize[ETickLeft];};
	/*!\brief returns the right main tick size in pixels
	
	\sa GetMainTicksSize
	*/
	double GetRightMainTicksSize()const									{	return m_pMainTicksSize[ETickRight];};
	/*!\brief returns the top main tick size in pixels
	
	\sa GetMainTicksSize
	*/
	double GetTopMainTicksSize()const									{	return m_pMainTicksSize[ETickTop];};

	/*!\brief Sets the secondary tick size
	
	  \param eIndex enumeration identifying the ticks position
	  \param pixels dimension of the tick in pixels (can be negative)
	*/
	void SetSecondTicksSize(ETickIndex eIndex, double pixels)			{ m_pSecondTicksSize[eIndex] = pixels;};
	/*! \brief sets the bottom secondary tick size in pixels
	\sa SetSecondTicksSize
	*/
	void SetBottomSecondTicksSize(double pixels)						{	m_pSecondTicksSize[ETickBottom] = pixels;};
	/*! \brief sets the left secondary tick size in pixels
	\sa SetSecondTicksSize
	*/
	void SetLeftSecondTicksSize(double pixels)							{	m_pSecondTicksSize[ETickLeft] = pixels;};
	/*! \brief sets the right secondary tick size in pixels
	\sa SetSecondTicksSize
	*/
	void SetRightSecondTicksSize(double pixels)							{	m_pSecondTicksSize[ETickRight] = pixels;};
	/*! \brief sets the top secondary tick size in pixels
	\sa SetSecondTicksSize
	*/
	void SetTopSecondTicksSize(double pixels)							{	m_pSecondTicksSize[ETickTop] = pixels;};	
	/*! \brief sets all the secondary tick size in pixels
	\sa SetSecondTicksSize
	*/
	void SetAllSecondTicksSize(double pixels)							{	for (size_t i=0;i<4;i++) m_pSecondTicksSize[i] = pixels;};

	/*!\brief Returns the secondary tick size
	
	  \param eIndex enumeration identifying the ticks position
	*/
	double GetSecondTicksSize(ETickIndex eIndex) const			{	return m_pSecondTicksSize[eIndex]; };
	/*!\brief returns the bottom secondary tick size in pixels
	
	\sa GetMainTicksSize, GetSecondTicksSize
	*/
	double GetBottomSecondTicksSize()const						{	return m_pSecondTicksSize[ETickBottom];};
	/*!\brief returns the left secondary tick size in pixels
	
	\sa GetMainTicksSize, GetSecondTicksSize
	*/
	double GetLeftSecondTicksSize()const						{	return m_pSecondTicksSize[ETickLeft];};
	/*!\brief returns the right secondary tick size in pixels
	
	\sa GetMainTicksSize, GetSecondTicksSize
	*/
	double GetRightSecondTicksSizeBottom()const					{	return m_pSecondTicksSize[ETickRight];};
	/*!\brief returns the top secondary tick size in pixels
	
	\sa GetMainTicksSize, GetSecondTicksSize
	*/
	double GetTopSecondTicksSizeBottom()const					{	return m_pSecondTicksSize[ETickTop];};

	/*!\brief Sets the secondary tick number
	
	  \param eIndex enumeration identifying the ticks position
	  \param nb the number of secondary ticks
	*/
	void SetSecondTicksNb(ETickIndex eIndex, UINT nb)			{	m_pSecondTicksNb[eIndex] = nb;};
	/*! \brief sets the bottom secondary tick number
	\sa SetSecondTicksNb
	*/
	void SetBottomSecondTicksNb(UINT nb)						{	m_pSecondTicksNb[ETickBottom] = nb;};
	/*! \brief sets the left secondary tick number
	\sa SetSecondTicksNb
	*/
	void SetLeftSecondTicksNb(UINT nb)							{	m_pSecondTicksNb[ETickLeft] = nb;};
	/*! \brief sets the right secondary tick number
	\sa SetSecondTicksNb
	*/
	void SetRightSecondTicksNb(UINT nb)							{	m_pSecondTicksNb[ETickRight] = nb;};
	/*! \brief sets the top secondary tick number
	\sa SetSecondTicksNb
	*/
	void SetTopSecondTicksNb(UINT nb)							{	m_pSecondTicksNb[ETickTop] = nb;};
	/*! \brief sets all the secondary tick number
	\sa SetSecondTicksNb
	*/
	void SetAllSecondTicksNb(UINT nb)							{	for (UINT i=0;i<4;i++) m_pSecondTicksNb[i] = nb;};

	/*!\brief Returns the secondary tick number
	
	  \param eIndex enumeration identifying the ticks position
	*/
	double GetSecondTicksNb(ETickIndex eIndex) const			{	return m_pSecondTicksNb[eIndex]; };
	/*! \brief returns the bottom secondary tick number
	\sa GetSecondTicksNb
	*/
	double GetBottomSecondTicksNb()const						{	return m_pSecondTicksNb[ETickBottom];};
	/*! \brief returns the left secondary tick number
	\sa GetSecondTicksNb
	*/
	double GetLeftSecondTicksNb()const							{	return m_pSecondTicksNb[ETickLeft];};
	/*! \brief returns the right secondary tick number
	\sa GetSecondTicksNb
	*/
	double GetRightSecondTicksNb()const							{	return m_pSecondTicksNb[ETickRight];};
	/*! \brief returns the top secondary tick number
	\sa GetSecondTicksNb
	*/
	double GetTopSecondTicksNb()const							{	return m_pSecondTicksNb[ETickTop];};
	//@}
	
	//! \name Log Axis
	//@{
	/*! \brief Turns on/off logarithmic scale
	
	  \warning not implemented yet
	*/
	bool IsLogAxis(EAxis i) const {	ASSERT(i==0 || i==1); return m_pLogAxis[i];};
	void SetLogAxis(EAxis i, bool logstate) {	ASSERT(i==0 || i==1); m_pLogAxis[i]=logstate;};
	//@}

	//! \name Borders
	//@{
	//! Returns a rect with the border size (in pixels)
	const CPGLRectD& GetBorders() const						{	return m_rBorders;};
	//! Return a rect of bool with the border automatic computation bit
	const CPGLRectB& GetAutoBorders() const					{	return m_rAutoBorders;};
	//! Sets border size (in pixels)
	void SetBorders(const CPGLRectD& rBorders)				{	m_rBorders = rBorders;};
	//! Sets border size automatic generation bit
	void SetAutoBorders(const CPGLRectB& rAutoBorders)		{	m_rAutoBorders = rAutoBorders;};
	//! returns the border style line, const
	const CPGLLine& GetBorderStyle() const					{	return m_lBoxTicks;};
	//! returns the border style
	CPGLLine& GetBorderStyle()								{	return m_lBoxTicks;};
	//! returns border line visibility
	const CPGLRectB& GetBorderLineVisibility( ) const		{	return m_rBorderLineVis;};
	//! Sets border line on/off
	void SetBorderLineVisibility( const CPGLRectB& rBorderLineVis)	{ m_rBorderLineVis = rBorderLineVis;}; 
	//@}

    //! \name Significative numbers
    //@{
    //! Set the maximum of significative numbers
    void SetMaxSignificativeNumbers(size_t n_);
    void SetDecimalSignificativeNumbers(size_t n_);
    size_t GetMaxSignificativeNumbers() const;
    size_t GetDecimalSignificativeNumbers() const;
    //@}

	//! \name Internal drawing functions
	//@{
	virtual void PlotGfx(gfxinterface::CGfxInterface& gfx);
	//! draw grids
	void DrawGridGfx(EAxis eAxe,gfxinterface::CGfxInterface& gfx);
	//! draw labels and numbering
	void DrawNumbersGfx(gfxinterface::CGfxInterface& gfx);
	//! draw border and ticks
	void DrawLinesGfx(gfxinterface::CGfxInterface& gfx);
	//@}

	//! \name Clipping
	//@{
	//! Puts clipping region on the stack
	void UnClipGfx(gfxinterface::CGfxInterface& gfx);
	//! Pops the clipping region
	void ClipGfx(gfxinterface::CGfxInterface& gfx);
	//@}

	//! \name GUI
	//@{
	void AddPropertyPage(CPropertySheet* pPropSheet);
	HTREEITEM AddPropTree(CTreeCtrl* pTree, HTREEITEM hParent);
	//! pan the chart of dx,dy pixels
	void Pan(double dx, double dy);
	//! zoom scale
	void ZoomScale(double x, double y);
	//@}

/*	
	//! \brief Scripting
	//@{
	enum EAxe2DProp
	{
		Axe2DPropUnknow,
		Axe2DPropLeftLabel,
		Axe2DPropRightLabel,
		Axe2DPropTopLabel,
		Axe2DPropBottomLabel,
	};
	PGL_DECLARE_SCRIPTING(Axe2D);
	//@}
*/
	//! \name Serialization and debuggin
	//@{
	///!Serialize functions
	void SerializeXML( CPGLArchive& ar);

	//! Debuggin functions
	#ifdef _DEBUG
	    virtual void Dump( CDumpContext& dc ) const;
	    virtual void AssertValid() const;    // Override
	#endif
	//@}

protected:
	//! \name Protected methods
	//@{
	//! Estimating numbering string size
	void EstimateNumberingSize();
	//@}

protected:
	//! \name Attributes
	//@{
	//! a pointer to the associated view
	CPGLView2D* m_pView;
	//! Symetric numbering
	bool m_bAxisSquare;
	//! axes labels: [bottom, left, right, top], ...
	CPGLText m_pLabels[4];
	//! Dirty bit for labels
	bool m_bLabelsDirty;
	//! axes numbering
	CPGLText m_pNumbers[4];
	//! axes numbering position
	double m_pNumberPos[4];
	//! number exponent limit
	UINT m_pNumberExpLimits[4];
	//! beginning value of axes
	double m_pStarts[2];
	//! Main ticks size
	double m_pMainTicksSize[4];
	//! Secondary Ticks size
	double m_pSecondTicksSize[4];
	//! number of secondary ticks
	UINT m_pSecondTicksNb[4];
	//! end value of axes
	double m_pEnds[2];
	//! length of steps for numbering
	double m_pSteps[2];
	//! true if step is computed automaticaly
	bool m_pAutoSteps[2];
	//! desired number of line in grid
	UINT m_pNSteps[2];
	//! log axis
	bool m_pLogAxis[2];
	//! Time labels
	bool m_bTimeLabel;
	//! Time step : 1 in coordinate = 1 time step
	COleDateTimeSpan m_tsDt;
	//! Time at 0.
	COleDateTime m_tTimeLabelOrig;
	//! String describing time label
	CString m_sTimeLabel;
	// horizontal grids style
	CPGLLine m_lHorGrid;
	//! vertical grids style
	CPGLLine m_lVerGrid;
	//! box and ticks style
	CPGLLine m_lBoxTicks;
	//! borders size
	CPGLRectD m_rBorders;
	//! automatic borders...
	CPGLRectB m_rAutoBorders;
	//! border line visibility
	CPGLRectB m_rBorderLineVis;
    //! max significative number
    size_t m_max_significative_number;
    //! decimal significative number
    size_t m_decimal_significative_number;
	//@}
};

PGL_DECLARE_SMARTPTR( CPGLAxe2D );

/*! \example axiscustom.cpp
Example of axis customizations.

\image html axiscustom.png "Axis customization examples"
*/

#endif // !defined(AFX_PGLAXE2D_H__4DACBB7A_9EFC_11D4_8A95_D4B14EEC3D7F__INCLUDED_)
